using System;
using System.Diagnostics.Contracts;
using System.Linq;
using MyUtils;

using XTrace.Viewer.Filter;
using XTrace.Viewer.Properties;

namespace XTrace.Viewer
{
	class StringSetFilterEntryViewModel : ObservableObject
	{
		readonly string _name;
		readonly StringSetFilterViewModel _filterViewModel;

		public StringSetFilter Filter
		{
			get
			{
				return _filterViewModel.StringSetFilterModel;
			}
		}

		string FieldName
		{
			get { return _filterViewModel.FieldName; }
		}

		internal StringSetFilterEntryViewModel(string name, StringSetFilterViewModel filterViewModel)
		{
			_name = name;
			_filterViewModel = filterViewModel;
			TryDetectGuidsAndNumbers();
		}

		public string Name
		{
			get
			{
				return _name;
			}
		}

		public bool IsBadName { get; private set; }

		public string BadEntryDescription { get; private set; }

		public bool IsIncluded
		{
			get
			{
				var fm = Filter;
				return fm != null && fm.IncludesHashSet.Contains(_name);
			}
			set
			{
				if (IsIncluded != value)
				{
					if (value)
					{
						if (Filter.IncludesHashSet.Add(_name))
						{
							Filter.InvokeGraphChanged();
							IsExcluded = false;
						}
					}
					else
					{
						if (Filter.IncludesHashSet.Remove(_name))
						{
							Filter.InvokeGraphChanged();
						}
					}
					OnPropertyChanged("IsIncluded");
				}
			}
		}

		public bool IsExcluded
		{
			get
			{
				var fm = Filter;
				return fm != null && fm.ExcludesHashSet.Contains(_name);
			}
			set
			{
				if (IsExcluded != value)
				{
					if (value)
					{
						if (Filter.ExcludesHashSet.Add(_name))
						{
							Filter.InvokeGraphChanged();
							IsIncluded = false;
						}
					}
					else
					{
						if (Filter.ExcludesHashSet.Remove(_name))
						{
							Filter.InvokeGraphChanged();
						}
					}
					OnPropertyChanged("IsExcluded");
				}
			}
		}

		[Pure]
		public static bool IsDigitExceptZero(char c)
		{
			if (c <= '\x00ff')
			{
				return (c >= '1' && c <= '9'); // do not include zero
			}
			return false;
			//return CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.DecimalDigitNumber;
		}

		private void TryDetectGuidsAndNumbers()
		{
			IsBadName = _name.Any(IsDigitExceptZero);
			if (IsBadName)
			{
				BadEntryDescription = "{0} contains digit. Consider specifiyng dynamic data in AdditionalInformation instead of {0}.".Arg(FieldName);
			}
		}

		public override string ToString()
		{
			return _name == string.Empty ? Resources.SsfevmEmpty : _name;
		}

		public void Notify()
		{
			OnPropertyChanged("Filter");
			OnPropertyChanged("IsIncluded");
			OnPropertyChanged("IsExcluded");
		}
	}
}